package edu.faytechcc.csc289.gui;

import edu.faytechcc.csc289.data.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.math.*;
import java.sql.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.filechooser.FileFilter;

/**
 * InventoryView class displays the inventory view in a JTable and allows
 * manipulation of database
 *
 * Mar 31, 2014
 *
 * @author William Robles
 */
public class InventoryView extends JPanel
{

    private final Dimension inventoryTableSize = new Dimension(1000, 200);
    private final Dimension uploadPanelSize = new Dimension(300, 150);

    private JPanel selectionPanel;

    private JButton exitButton, addButton, removeButton, editButton,
            chooseImageButton, refreshButton;

    private JFileChooser chooser = new JFileChooser();

    private JTable inventoryTable;
    private JScrollPane inventoryScrollPane;

    private FileLoader fL = new FileLoader();

    private JLabel costLabel, nameLabel, retailLabel, gameLabel,
            descriptionLabel, systemsLabel, qtyLabel, storeNumLabel;

    private JTextField descriptionTextField, nameTextField, costTextField,
            retailTextField, qtyTextField;

    private JTextArea filePathJTextArea;

    private JComboBox systemComboBox, storeNumComboBox;
    private ArrayList<String> systemsList = new ArrayList<>();

    private ImageIcon gameImage = new ImageIcon();
    private ImageIcon refreshImage;

    private SimulacraDbConnection sDb;

    private ResultSet invResults;

    private DataDisplay dD;

    public InventoryView()
    {
        this.sDb = new SimulacraDbConnection();
        this.setLayout(new BorderLayout());

        fL.getFile(systemsList, "systems");

        dD = new DataDisplay();

        buildInventoryDisplay();
        buildInputPanel();
        buildImageUploadPanel();
        buildBottomPanel();
    }

    /**
     * buildInventoryDisplay method creates the inventoryTable and displays
     */
    private void buildInventoryDisplay()
    {
        inventoryTable = new JTable(dD.buildTable(invResults, sDb));
        inventoryTable.getTableHeader().setReorderingAllowed(false);
        inventoryTable.removeColumn(inventoryTable.getColumnModel().getColumn(
                                           inventoryTable.getColumnCount() - 1));
        inventoryTable.getClass();
        inventoryTable.setPreferredScrollableViewportSize(inventoryTableSize);
        inventoryTable.setAutoCreateRowSorter(true);
        inventoryTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        inventoryTable.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.
                                                                        RAISED));

        inventoryTable.getSelectionModel().addListSelectionListener(new 
                                                            SelectionListener());

        inventoryScrollPane = new JScrollPane(inventoryTable);

        this.add(inventoryScrollPane, BorderLayout.NORTH);
    }

    /**
     * buildSelectionPanel method creates the selection panel that includes the
     * gameImage and the sales JTextArea
     */
    private void buildInputPanel()
    {
        selectionPanel = new JPanel();
        selectionPanel.setLayout(new BorderLayout());
        JPanel temp = new JPanel();
        temp.setLayout(new GridLayout(5, 1));
        JPanel temp2 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        refreshImage = new ImageIcon("res/refresh.png");

        addButton = new JButton("Add");
        addButton.setToolTipText("Add new item");
        addButton.addActionListener(new ButtonListener());
        removeButton = new JButton("Remove");
        removeButton.setToolTipText("Remove item");
        removeButton.addActionListener(new ButtonListener());
        editButton = new JButton("Edit");
        editButton.setToolTipText("Edit item");
        editButton.addActionListener(new ButtonListener());
        refreshButton = new JButton(refreshImage);
        refreshButton.setToolTipText("Refresh Inventory Table");
        refreshButton.addActionListener(new ButtonListener());

        gameLabel = new JLabel(gameImage);

        temp.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));

        storeNumLabel = new JLabel("Store #: ");
        costLabel = new JLabel("Cost: ");
        retailLabel = new JLabel("Retail Price: ");
        nameLabel = new JLabel("Name: ");
        descriptionLabel = new JLabel("Description: ");
        systemsLabel = new JLabel("System Type: ");
        qtyLabel = new JLabel("Quantity: ");

        storeNumComboBox = new JComboBox(dD.returnStores().toArray());
        costTextField = new JTextField(6);
        retailTextField = new JTextField(6);
        nameTextField = new JTextField(15);
        qtyTextField = new JTextField(3);
        descriptionTextField = new JTextField(20);

        systemComboBox = new JComboBox(systemsList.toArray());

        temp2.add(storeNumLabel);
        temp2.add(storeNumComboBox);
        temp2.add(nameLabel);
        temp2.add(nameTextField);
        temp.add(temp2);

        temp2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        temp2.add(descriptionLabel);
        temp2.add(descriptionTextField);
        temp.add(temp2);

        temp2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        temp2.add(costLabel);
        temp2.add(costTextField);
        temp2.add(retailLabel);
        temp2.add(retailTextField);
        temp.add(temp2);

        temp2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        temp2.add(systemsLabel);
        temp2.add(systemComboBox);
        temp2.add(qtyLabel);
        temp2.add(qtyTextField);
        temp.add(temp2);

        temp2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        temp2.add(addButton);
        temp2.add(removeButton);
        temp2.add(editButton);
        temp2.add(refreshButton);
        temp.add(temp2);

        selectionPanel.add(temp, BorderLayout.WEST);
        selectionPanel.add(gameLabel, BorderLayout.CENTER);

        this.add(selectionPanel, BorderLayout.CENTER);
    }

    /**
     * buildImageUploadPanel method creates the panel that allows selection of
     * image to be uploaded
     */
    private void buildImageUploadPanel()
    {
        JPanel temp = new JPanel(new BorderLayout());
        JPanel temp2 = new JPanel(new FlowLayout(FlowLayout.CENTER));

        filePathJTextArea = new JTextArea(15, 27);
        filePathJTextArea.setEditable(false);
        filePathJTextArea.setLineWrap(true);

        chooseImageButton = new JButton("Select an Image");

        temp.setPreferredSize(uploadPanelSize);
        temp.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));

        temp2.add(filePathJTextArea);
        temp.add(temp2, BorderLayout.CENTER);

        temp2 = new JPanel(new FlowLayout(FlowLayout.CENTER));
        temp2.add(chooseImageButton);
        chooseImageButton.addActionListener(new ButtonListener());
        temp.add(temp2, BorderLayout.SOUTH);

        selectionPanel.add(temp, BorderLayout.EAST);
    }

    /**
     * buildBottomPanel method creates the lower panel with an exit button
     */
    private void buildBottomPanel()
    {
        JPanel temp = new JPanel(new FlowLayout(FlowLayout.LEADING));
        JPanel temp2 = new JPanel(new BorderLayout());
        temp2.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
        JLabel inventoryLabel = new JLabel("Inventory Management", 
                                                        SwingConstants.CENTER);
        inventoryLabel.setFont(new Font("Serif", Font.BOLD, 25));

        temp2.add(inventoryLabel, BorderLayout.CENTER);

        exitButton = new JButton("Exit");

        exitButton.addActionListener(new ButtonListener());

        temp.add(exitButton);
        temp2.add(temp, BorderLayout.WEST);

        this.add(temp2, BorderLayout.SOUTH);
    }

    /**
     * addItem method adds new inventory to DB
     */
    private void addItem(ActionEvent ae)
    {
        if (dD.confirmAction(ae))
        {
            invResults = sDb.getInventory();

            if (dD.dataIsValid(nameTextField.getText(), descriptionTextField.
                            getText(),costTextField.getText(), retailTextField.
                                    getText(),qtyTextField.getText(),gameImage))
            {
                int storeNum = Integer.parseInt(storeNumComboBox.
                                                  getSelectedItem().toString());
                String itemName = nameTextField.getText();
                String description = descriptionTextField.getText();
                BigDecimal cost = new BigDecimal(costTextField.getText());
                BigDecimal retail = new BigDecimal(retailTextField.getText());
                String system = systemComboBox.getSelectedItem().toString();
                int qty = Integer.parseInt(qtyTextField.getText());

                try
                {
                    if (ae.getSource() == addButton)
                    {
                        invResults.moveToInsertRow();
                    }
                    else if (ae.getSource() == editButton)
                    {
                        invResults.absolute(inventoryTable.convertRowIndexToModel(
                                inventoryTable.getSelectedRow()) + 1);
                    }

                    invResults.updateInt("Store#", storeNum);
                    invResults.updateString("Item Name", itemName);
                    invResults.updateString("Description", description);
                    invResults.updateBigDecimal("Cost", cost);
                    invResults.updateBigDecimal("Retail Price", retail);
                    invResults.updateString("System", system);
                    invResults.updateInt("Quantity", qty);

                    if (ae.getSource() == editButton && !filePathJTextArea.
                                                            getText().isEmpty())
                    {
                        invResults.updateBlob("Picture", dD.imageToBlob(
                                gameImage, filePathJTextArea.getText()));
                    }

                    if (ae.getSource() == addButton)
                    {
                        invResults.updateBlob("Picture", dD.imageToBlob(
                                gameImage, filePathJTextArea.getText()));
                        invResults.insertRow();
                        filePathJTextArea.setText(null);
                    }
                    else if (ae.getSource() == editButton)
                    {
                        invResults.updateRow();
                    }

                    invResults.close();
                }
                catch (SQLException ex)
                {
                    System.err.println("ERROR: " + ex.getMessage());
                    System.exit(24);
                }
                catch (Exception ex)
                {
                    System.err.println("ERROR: " + ex.getMessage());
                    System.exit(24);
                }

                dD.refreshTable(inventoryTable, invResults, sDb);
                clearFields();
            }
        }
    }
    
    /**
     * clearFields method clears textfields and image
     */
    private void clearFields()
    {
        nameTextField.setText("");
        descriptionTextField.setText("");
        nameTextField.setText("");
        costTextField.setText("");
        retailTextField.setText("");
        qtyTextField.setText("");
        gameImage = null;
        gameLabel.setIcon(gameImage);
    }

    /**
     * removeItem method removes the selected item from the database
     */
    private void removeItem(ActionEvent ae)
    {
        if (dD.confirmAction(ae))
        {
            invResults = sDb.getInventory();

            try
            {
                invResults.absolute(inventoryTable.getSelectedRow() + 1);
                invResults.deleteRow();

                invResults.close();
            }
            catch (SQLException ex)
            {
                System.err.println("ERROR: " + ex.getMessage());
                System.exit(24);
            }

            dD.refreshTable(inventoryTable, invResults, sDb);
            clearFields();
        }
    }

    /**
     * showSelectedPic method displays the selected item from table picture
     */
    private void showSelectedItem()
    {
        invResults = sDb.getInventory();

        try
        {
            invResults.absolute(inventoryTable.convertRowIndexToModel(
                    inventoryTable.getSelectedRow()) + 1);
            Blob imageBlob = invResults.getBlob("Picture");
            byte[] bytes = imageBlob.getBytes(1, (int) imageBlob.length());
            imageBlob.free();

            storeNumComboBox.setSelectedItem(invResults.getInt("Store#"));
            nameTextField.setText(invResults.getString("Item Name"));
            descriptionTextField.setText(invResults.getString("Description"));
            costTextField.setText(invResults.getBigDecimal("Cost").toString());
            retailTextField.setText(invResults.getBigDecimal("Retail Price").
                                                                    toString());
            systemComboBox.setSelectedItem(invResults.getString("System"));
            qtyTextField.setText(invResults.getString("Quantity"));

            gameImage = new ImageIcon(bytes);

            gameLabel.setIcon(gameImage);

            invResults.close();
        }
        catch (SQLException ex)
        {
            System.err.println("ERROR: " + ex.getMessage());
            System.exit(24);
        }
    }

    /**
     * setChosenImage selects the image to be user for input
     */
    private void setChosenImage()
    {
        FileFilter imageFilter = new FileNameExtensionFilter("Image files",
                ImageIO.getReaderFileSuffixes());
        chooser.setFileFilter(imageFilter);
        chooser.setAcceptAllFileFilterUsed(false);
        int returnVal = chooser.showOpenDialog(null);

        if (returnVal == JFileChooser.APPROVE_OPTION)
        {

            File file = chooser.getSelectedFile();

            if (file.getName().toLowerCase().endsWith(".jpg") || file.getName().
                    toLowerCase().endsWith(".gif") || file.getName().
                    toLowerCase().endsWith(".png") || file.getName().
                    toLowerCase().endsWith(".bmp"))
            {
                filePathJTextArea.setText("Selected File: " + file.toString());
                gameImage = new ImageIcon(file.toString());

                gameImage = dD.scaleImage(gameImage);

                gameLabel.setIcon(gameImage);
            }
            else
            {
                JOptionPane.showMessageDialog(null,
                        "ERROR: Only .jpg, .gif, .png, or .bmp files",
                        "Error Message",
                        JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private class SelectionListener implements ListSelectionListener
    {

        public SelectionListener()
        {

        }

        @Override
        public void valueChanged(ListSelectionEvent lse)
        {
            if (inventoryTable.getSelectedRow() != -1)
            {
                showSelectedItem();
            }
        }
    }

    private class ButtonListener implements ActionListener
    {

        public ButtonListener()
        {
        }

        @Override
        public void actionPerformed(ActionEvent ae)
        {
            if (ae.getSource() == chooseImageButton)
            {
                setChosenImage();
            }
            else if (ae.getSource() == exitButton)
            {
                Component c = (Component) ae.getSource();

                JFrame frame = (JFrame) SwingUtilities.getRoot(c);

                frame.dispose();
            }
            else if (ae.getSource() == addButton || ae.getSource() == editButton)
            {
                addItem(ae);
            }
            else if (ae.getSource() == removeButton)
            {
                removeItem(ae);
            }
            else if (ae.getSource() == refreshButton)
            {
                dD.refreshTable(inventoryTable, invResults, sDb);
            }
        }
    }
}
